<?php

declare(strict_types=1);

namespace Core\HyperfUnit;

use Psr\SimpleCache\InvalidArgumentException;
use Hyperf\Context\Context;

class Callback
{

    /**
     * 回调式缓存
     * @param string $key KEY
     * @param callable $callback 回调
     * @param int $ttl 有效期
     * @return mixed
     */
    public static function cache(string $key, callable $callback, int $ttl = 10000000): mixed
    {
        try {
            $key = 'cc:' . md5($key);
            $cache = cache();
            if ($cache->has($key)) {
                return $cache->get($key);
            }
            $data = $callback();
            $cache->set($key, $data, $ttl);
            return $data;
        } catch (InvalidArgumentException) {
            return $callback();
        }
    }


    /**
     * 分组回调时缓存
     * @param string $group
     * @param string $name
     * @param callable $callback
     * @param int $ttl
     * @return mixed
     */
    public static function GroupCache(string $group, string $name, callable $callback, int $ttl = 10000000): mixed
    {
        try {
            $key = 'cc:' . md5($group);
            $cache = cache();
            $result = [];
            if ($cache->has($key)) {
                $result = $cache->get($key);
                if (isset($result[$name])) {
                    if ($result[$name]['ttl'] === 0 || $result[$name]['ttl'] > time()) {
                        return $result[$name]['value'];
                    }
                }
            }
            $result[$name] = ['value' => $callback(), 'ttl' => $ttl ? (time() + $ttl) : 0];

            $cache->set($key, $result, $ttl);
            return $result[$name]['value'];
        } catch (InvalidArgumentException) {
            return $callback();
        }
    }


    /**
     * 清空组缓存
     * @param string $group
     * @return void
     * @throws InvalidArgumentException
     */
    public static function ClearGroup(string $group): void
    {
        $key = 'cc:' . md5($group);
        cache()->delete($key);
    }


    /**
     * 上下文储存
     * @param string $key
     * @param callable $callback
     * @return mixed
     */
    public static function context(string $key, $callback)
    {
        try {
            $key = 'cc:' . md5($key);
            if (Context::has($key)) {
                return Context::get($key);
            }
            $data = $callback();
            Context::set($key, $data);
            return $data;
        } catch (InvalidArgumentException) {
            return $callback();
        }
    }
}